package cn.songshijia.mycodelabschallenge;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import com.huawei.agconnect.auth.AGConnectAuth;
import com.huawei.agconnect.cloud.database.AGConnectCloudDB;
import com.huawei.agconnect.cloud.database.CloudDBZone;
import com.huawei.agconnect.cloud.database.CloudDBZoneConfig;
import com.huawei.agconnect.cloud.database.CloudDBZoneObjectList;
import com.huawei.agconnect.cloud.database.CloudDBZoneQuery;
import com.huawei.agconnect.cloud.database.ListenerHandler;
import com.huawei.agconnect.cloud.database.OnSnapshotListener;
import com.huawei.agconnect.cloud.database.exceptions.AGConnectCloudDBException;
import com.huawei.hmf.tasks.OnFailureListener;
import com.huawei.hmf.tasks.OnSuccessListener;
import com.huawei.hmf.tasks.Task;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class DataActivity extends AppCompatActivity {
    private static final String TAG = DataActivity.class.getName();
    private CloudDBZone mCloudDBZone;
    private AGConnectCloudDB mCloudDB;
    private Context context;
    private TextView showData;
    private ListView digitAssetList;
    private SimpleAdapter listAdapter;
    private ListenerHandler mRegister;
    private List<Map<String, Object>> listData;
    private Handler handler = new Handler();
    private ImageView imageView;
    private EditText editText;
    private TextView textView;
    private Uri uri;
    private String type = "picture";
    private List<DigitalAsset> digitalAssets = new ArrayList<>();
    private String phoneNumber = AGConnectAuth.getInstance().getCurrentUser().getPhone();
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);

    //选取图片
    private final ActivityResultLauncher<String> launcher = registerForActivityResult(
            new ActivityResultContracts.GetContent(), result -> {
                uri = result;
                switch (type) {
                    case "picture":
                    case "audio":
                    case "file":
                        textView.setText(result.getPath());
                        break;
                    default:
                        System.out.println("invalid type");
                }
            }
    );

    //调用相册选择图片
    protected void mLaunch(String type) {
        launcher.launch(type);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_data);
        showData = findViewById(R.id.show_data);
        digitAssetList = findViewById(R.id.digit_assets);
        EditText name = findViewById(R.id.set_name);
        imageView = findViewById(R.id.image_view);
        editText = findViewById(R.id.enter_text);
        textView = findViewById(R.id.show_uri);

        findViewById(R.id.logout).setOnClickListener(v -> {
            AGConnectAuth.getInstance().signOut();
            Toast.makeText(this, "已注销", Toast.LENGTH_LONG).show();
            Intent intent = new Intent();
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setClass(this, MainActivity.class);
            startActivity(intent);
        });

        findViewById(R.id.wipe).setOnClickListener(v -> {
            deleteDigitalAssetsAsync(digitalAssets);
        });

        context = this;
        initCloudDBZone(this);
        addSubscription();

        findViewById(R.id.insert).setOnClickListener(v -> {
            DigitalAsset da = new DigitalAsset();
            String phone = AGConnectAuth.getInstance().getCurrentUser().getPhone();
            da.setPhoneNumber(phone);
            da.setName(name.getText().toString());
            da.setDate(Calendar.getInstance().getTime());
            switch (type) {
                case "picture":
                    da.setType("图片");
                    break;
                case "audio":
                    da.setType("音频");
                    break;
                case "file":
                    da.setType("文件");
                    break;
                case "text":
                    da.setType("文本");
                    break;
                default:
                    System.out.println("invalid type");
            }
            switch (type) {
                case "picture":
                case "audio":
                case "file":
                    if (uri != null) {
                        try {
                            InputStream is = context.getContentResolver().openInputStream(uri);
                            byte[] data = new byte[is.available()];
                            is.read(data);
                            da.setContent(data);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                case "text":
                    da.setContent(editText.getText().toString().getBytes(StandardCharsets.UTF_8));
                    break;
                default:
                    System.out.println("invalid type");
            }
            upsertDigitalAsset(da);
        });


        findViewById(R.id.choose_content).setOnClickListener(v -> {
            switch (type) {
                case "picture":
                    mLaunch("image/*");
                    break;
                case "audio":
                    mLaunch("audio/*");
                    break;
                case "file":
                    mLaunch("*/*");
                    break;
                case "text":
                    editText.setVisibility(View.VISIBLE);
                    break;
                default:
                    System.out.println("invalid type");
            }
        });

        RadioGroup radioGroup = findViewById(R.id.radioGroup);
        //第一种获得单选按钮值的方法
        //为radioGroup设置一个监听器:setOnCheckedChanged()
        radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
            RadioButton radioButton = findViewById(checkedId);
            type = radioButton.getText().toString();
            editText.setText("");
            textView.setText("");
            uri = null;
        });
    }

    // bookInfoList为查询操作或侦听器返回的数据集。
    public void deleteDigitalAssetsAsync(List<DigitalAsset> digitalAssetList) {
        if (mCloudDBZone == null) {
            Log.w(TAG, "CloudDBZone is null, try re-open it");
            return;
        }

        Task<Integer> deleteTask = mCloudDBZone.executeDelete(digitalAssetList);
        deleteTask.addOnSuccessListener(new OnSuccessListener<Integer>() {
            @Override
            public void onSuccess(Integer integer) {
                Log.i(TAG, "digitalAssetList delete success");
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                Log.e(TAG, "digitalAssetList delete fail");
            }
        });
    }

    private void upsertDigitalAsset(DigitalAsset da) {
        checkCloudDBZone();
        if (mCloudDBZone == null) {
            Log.w(TAG, "CloudDBZone is null, try re-open it");
            return;
        }

        CloudDBZoneQuery<DigitalAsset> query = CloudDBZoneQuery.where(DigitalAsset.class);
        Task<Long> countQueryTask = mCloudDBZone.executeCountQuery(query, "id",
                CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
        countQueryTask.addOnSuccessListener(new OnSuccessListener<Long>() {
            @Override
            public void onSuccess(Long aLong) {
                Log.i(TAG, "The total number of DigitalAsset is " + aLong);
                da.setId((int) (aLong + 1));
                Task<Integer> upsertTask = mCloudDBZone.executeUpsert(da);
                upsertTask.addOnSuccessListener(new OnSuccessListener<Integer>() {
                    @Override
                    public void onSuccess(Integer cloudDBZoneResult) {
                        Log.i(TAG, "Upsert " + cloudDBZoneResult + " records");
                        Toast.makeText(context, "Upsert " + cloudDBZoneResult + " records",
                                Toast.LENGTH_SHORT).show();
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(Exception e) {
                        Log.e(TAG, "Insert DigitalAsset failed：" + e.getMessage());
                        Toast.makeText(context, "Insert DigitalAsset failed：" + e.getMessage(),
                                Toast.LENGTH_LONG).show();
                        e.printStackTrace();
                    }
                });
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                Log.w(TAG, "Count query is failed: " + Log.getStackTraceString(e));
            }
        });
    }

    private void checkCloudDBZone() {
        CloudDBZoneQuery<DigitalAsset> query = CloudDBZoneQuery.where(DigitalAsset.class);
        Task<Long> countQueryTask = mCloudDBZone.executeCountQuery(query, "id",
                CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
        countQueryTask.addOnSuccessListener(aLong -> Log.i(TAG, "The total number of DigitalAsset is " + aLong))
                .addOnFailureListener(e -> {
                    Log.w(TAG, "Count query is failed: " + Log.getStackTraceString(e));
                    initCloudDBZone(context);
                    addSubscription();
                });
    }

    private void createObjectType(AGConnectCloudDB mCloudDB) {
        try {
            mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo());
        } catch (AGConnectCloudDBException e) {
            e.printStackTrace();
        }
    }


    private void initCloudDBZone(Context context) {
        try {
            AGConnectCloudDB.initialize(context);
            mCloudDB = AGConnectCloudDB.getInstance();
            createObjectType(mCloudDB);
            CloudDBZoneConfig mConfig = new CloudDBZoneConfig("MyCodelabsChallenge",
                    CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
                    CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC);
            mConfig.setPersistenceEnabled(true);
            mCloudDBZone = mCloudDB.openCloudDBZone(mConfig, true);

            Task<CloudDBZone> openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true);
            openDBZoneTask.addOnSuccessListener(new OnSuccessListener<CloudDBZone>() {
                @Override
                public void onSuccess(CloudDBZone cloudDBZone) {
                    Log.i(TAG, "open cloudDBZone success");
                    mCloudDBZone = cloudDBZone;
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    Log.w(TAG, "open cloudDBZone failed for " + e.getMessage());
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(context, "cloudDBActions exception:" + e.getMessage(),
                    Toast.LENGTH_LONG).show();
        }
    }

    private OnSnapshotListener<DigitalAsset> mSnapshotListener = (cloudDBZoneSnapshot, e) -> {
        if (e != null) {
            Log.w(TAG, "onSnapshot: " + e.getMessage());
            return;
        }
        CloudDBZoneObjectList<DigitalAsset> snapshotObjects = cloudDBZoneSnapshot.getSnapshotObjects();
        digitalAssets.clear();
        listData = new ArrayList<>();
        try {
            if (snapshotObjects != null) {
                while (snapshotObjects.hasNext()) {
                    DigitalAsset digitalAsset = snapshotObjects.next();
                    digitalAssets.add(digitalAsset);
                    Map<String, Object> listItem = new HashMap<>();
                    listItem = new HashMap<>(); //必须在循环体里新建
                    listItem.put("id", digitalAsset.getId());
                    listItem.put("date", format.format(digitalAsset.getDate()));
                    listItem.put("type", digitalAsset.getType());
                    listItem.put("name", digitalAsset.getName());
                    listData.add(listItem);
                }

                listAdapter = new SimpleAdapter(this, listData, R.layout.digit_asset_item, //自行创建的列表项布局
                        new String[]{"id", "date", "type", "name"},
                        new int[]{R.id.tv_id, R.id.tv_date, R.id.tv_type,
                                R.id.tv_name});
                handler.post(() -> {
                    digitAssetList.setAdapter(listAdapter);
                    showData.setText("登陆用户" + phoneNumber + "的" + digitalAssets.size() + "条数据已获取到！");
                });
            }
        } catch (AGConnectCloudDBException snapshotException) {
            Log.w(TAG, "onSnapshot:(getObject) " + snapshotException.getMessage());
        } finally {
            cloudDBZoneSnapshot.release();
        }
    };

    public void addSubscription() {
        if (mCloudDBZone == null) {
            Log.w(TAG, "CloudDBZone is null, try re-open it");
            return;
        }

        try {
            CloudDBZoneQuery<DigitalAsset> snapshotQuery = CloudDBZoneQuery.where(DigitalAsset.class)
                    .equalTo("phoneNumber", phoneNumber);
            mRegister = mCloudDBZone.subscribeSnapshot(snapshotQuery,
                    CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY, mSnapshotListener);
        } catch (AGConnectCloudDBException e) {
            Log.w(TAG, "subscribeSnapshot: " + e.getMessage());
        }
    }

    @Override
    protected void onDestroy() {
        System.out.println("DataActivity.onDestroy");
        try {
            mRegister.remove();
            if (mCloudDB != null && mCloudDBZone != null) {
                mCloudDB.closeCloudDBZone(mCloudDBZone);
                System.out.println("mCloudDB.closeCloudDBZone(mCloudDBZone)");
            }
        } catch (AGConnectCloudDBException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

    @Override
    protected void onStop() {
        System.out.println("DataActivity.onStop");
        try {
            mRegister.remove();
            if (mCloudDB != null && mCloudDBZone != null) {
                mCloudDB.closeCloudDBZone(mCloudDBZone);
                System.out.println("mCloudDB.closeCloudDBZone(mCloudDBZone)");
            }
        } catch (AGConnectCloudDBException e) {
            e.printStackTrace();
        }
        super.onStop();
    }

    @Override
    protected void onResume() {
        initCloudDBZone(this);
        addSubscription();
        super.onResume();
    }
}